package com.example.demo.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.xml.bind.ValidationException;
import java.util.HashMap;
import java.util.Map;

/**
 * TODO
 * 统一异常处理类
 * @author caiyonglan
 * @email 627064518@qq.com
 * @date 2020/12/2 15:10
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 400 - Bad Request
     * 缺少请求参数 - MissingServletRequestParameterException
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Map<String, Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        System.out.println("缺少请求参数");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 400);
        map.put("msg", "缺少请求参数: " + e.getMessage());
        return map;
    }

    /**
     * 400 - Bad Request
     * 缺少请求参数 - HttpMessageNotReadableException
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Map<String, Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        System.out.println("缺少请求参数");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 400);
        map.put("msg", "缺少请求参数: " + e.getMessage());
        return map;
    }

    /**
     * 400 - Bad Request
     * 参数验证失败 - handleMethodArgumentNotValidException
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map<String, Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        System.out.println("参数验证失败");
        BindingResult result = e.getBindingResult();
        FieldError error = result.getFieldError();
        String field = error.getField();
        String code = error.getDefaultMessage();
        String msg = String.format("%s: %s", field, code);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", code);
        map.put("msg", "参数验证失败: " + msg);
        return map;
    }

    /**
     * 400 - Bad Request
     * 缺少请求参数 - BindException
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(BindException.class)
    public Map<String, Object> handleBindException(BindException e) {
        System.out.println("缺少请求参数");
        Map<String, Object> map = new HashMap<String, Object>();
        BindingResult result = e.getBindingResult();
        FieldError error = result.getFieldError();
        String field = error.getField();
        String code = error.getDefaultMessage();
        String msg = String.format("%s: %s", field, code);
        map.put("code", 400);
        map.put("msg", "缺少请求参数: " + msg);
        return map;
    }

//    /**
//     * 400 - Bad Request
//     * 新增数据出错 - ConstraintViolationException
//     */
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
//    public Map<String, Object> handleBindException(BindException e) {
//        System.out.println("缺少请求参数");
//        Map<String, Object> map = new HashMap<String, Object>();
//        BindingResult result = e.getBindingResult();
//        FieldError error = result.getFieldError();
//        String field = error.getField();
//        String code = error.getDefaultMessage();
//        String msg = String.format("%s: %s", field, code);
//        map.put("code", 400);
//        map.put("msg", msg);
//        return map;
//    }

    /**
     * 400 - Bad Request
     * 参数验证失败 - ValidationException
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ValidationException.class)
    public Map<String, Object> handleValidationException(ValidationException e) {
        System.out.println("参数验证失败");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 400);
        map.put("msg", "参数验证失败: " + e.getMessage());
        return map;
    }

    /**
     * 404 - NOT FOUND
     * NOT_FOUND - NoHandlerFoundException
     */
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public Map<String, Object> handleNoHandlerFoundException(NoHandlerFoundException e) {
        System.out.println("404 NOT FOUND");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 404);
        map.put("msg", "404 NOT FOUND: " + e.getMessage());
        return map;
    }

    /**
     * 405 - METHOD NOT ALLOWED
     * 方法不允许 - HttpRequestMethodNotSupportedException
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Map<String, Object> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        System.out.println("方法不允许");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 405);
        map.put("msg", "方法不允许: " + e.getMessage());
        return map;
    }

    /**
     * 415 - UNSUPPORTED MEDIA TYPE
     * 参数验证失败 - HttpMediaTypeNotSupportedException
     */
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Map<String, Object> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        System.out.println("参数验证失败");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 415);
        map.put("msg", "参数验证失败: " + e.getMessage());
        return map;
    }

    /**
     * 600 - BusinessException
     * 自定义业务异常 - BusinessException
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(BusinessException.class)
    public Map<String, Object> handleBusinessException(BusinessException e) {
        System.out.println("自定义业务异常");
        Map<String, Object> map = new HashMap<String, Object>(2);
        map.put("code", e.getCode());
        map.put("msg", "业务异常: " + e.getMsg());
        return map;
    }

    /**
     * 500 - Exception
     * 服务器错误 - Exception
     */
    @ExceptionHandler(Exception.class)
    public Map<String, Object> handleException(Exception e) {
        System.out.println("服务器错误");
        Map<String, Object> map = new HashMap<String, Object>(2);
        map.put("code", 500);
        map.put("msg", "服务器错误: " + e.getMessage());
        return map;
    }

}
